#include "InputXBoxController.h"
#include "WorldModel.h"
#include "UserInterface.h"

CInputXBoxController::CInputXBoxController(void)
{
}

CInputXBoxController::~CInputXBoxController(void)
{
}

bool CInputXBoxController::initialise(const LPDIRECTINPUT8)
{
	return true;
}

bool CInputXBoxController::initialiseActionMapping(Element root)
{
	list<Element> keyboard=root.Children();
	//for each line
	for(list<Element>::iterator i=keyboard.begin(); i!=keyboard.end(); i++)
	{
		int indexAction=getIndexAction(i->Name());
		if(indexAction==-1)
			return false;

		std::string key=i->Content();
		m_actionMapArray[indexAction]=UI->getDirectInputValue(key);
	}
	return true;
}

void CInputXBoxController::doUpdate(void)
{
	ZeroMemory( &m_state, sizeof(XINPUT_STATE));
	DWORD error;
	error=XInputGetState(0, &m_state);
	if(error==ERROR_DEVICE_NOT_CONNECTED)
		return;

	////handle forward, backward and strafe
	if(!getMovement())
		return;
 
	//handle turn left and right, up and down
	if(!getLookAndTurn())
		return;

	if(m_state.Gamepad.wButtons==m_actionMapArray[eChangeCamera])
	{
		if(WORLDMODEL->getCameraMode()==WORLDMODEL->eModeFPS)
			WORLDMODEL->setCameraMode(WORLDMODEL->eModeTPS);
		else
			WORLDMODEL->setCameraMode(WORLDMODEL->eModeFPS);
	}

}

bool CInputXBoxController::getMovement()
{
	const int valueMaxStick=32767;
	const int valueMinStick=-32768;

	//handle forward, backward and strafe
	if(m_actionMapArray[eMoveForward]==leftStick) //movement with left stick
	{
		//move forward and backward
		if(m_state.Gamepad.sThumbLY>=XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
		{
			WORLDMODEL->movePlayerForward((float)m_state.Gamepad.sThumbLY/(float)valueMaxStick);
		}
		else if (m_state.Gamepad.sThumbLY<=-XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
		{
			WORLDMODEL->movePlayerBackward((float)m_state.Gamepad.sThumbLY/(float)valueMinStick);
		}

		//strafe left and right
		if(m_state.Gamepad.sThumbLX>=XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
		{
			WORLDMODEL->strafePlayerRight((float)m_state.Gamepad.sThumbLX/(float)valueMaxStick);
		}
		else if (m_state.Gamepad.sThumbLX<=-XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
		{
			WORLDMODEL->strafePlayerLeft((float)m_state.Gamepad.sThumbLX/(float)valueMinStick);
		}
	}
	else if(m_actionMapArray[eMoveForward]==rightStick)//movement with right stick
	{
		//move forward and backward
		if(m_state.Gamepad.sThumbRY>=XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
		{
			WORLDMODEL->movePlayerForward((float)m_state.Gamepad.sThumbRY/(float)valueMaxStick);
		}
		else if(m_state.Gamepad.sThumbRY<=-XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
		{
			WORLDMODEL->movePlayerBackward((float)m_state.Gamepad.sThumbRY/(float)valueMinStick);
		}

		//strafe left and right
		if(m_state.Gamepad.sThumbRX>=XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
		{
			WORLDMODEL->strafePlayerRight((float)m_state.Gamepad.sThumbRX/(float)valueMaxStick);
		}
		else if(m_state.Gamepad.sThumbRX<=-XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
		{
			WORLDMODEL->strafePlayerLeft(-1*((float)m_state.Gamepad.sThumbRX/(float)valueMinStick));
		}
	}
	else
		return false;

	return true;

}

bool CInputXBoxController::getLookAndTurn()
{
	const int valueMaxStick=32767;

	//handle turn left and right, up and down
	if(m_actionMapArray[eTurnLeftRight]==leftStick)
	{
		if(m_state.Gamepad.sThumbLX>=XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ||
			m_state.Gamepad.sThumbLX<=-XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE )
				WORLDMODEL->turnPlayerLeftRight(20*(float)m_state.Gamepad.sThumbLX/(float)valueMaxStick);

		if(m_state.Gamepad.sThumbLY>=XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ||
			m_state.Gamepad.sThumbLY<=-XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
				WORLDMODEL->playerLookUpDown(-10*((float)m_state.Gamepad.sThumbLY/(float)valueMaxStick));
	}
	else if(m_actionMapArray[eTurnLeftRight]==rightStick)
	{
		if(m_state.Gamepad.sThumbRX>=XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ||
			m_state.Gamepad.sThumbRX<=-XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
				WORLDMODEL->turnPlayerLeftRight(20*(float)m_state.Gamepad.sThumbRX/(float)valueMaxStick);

		if(m_state.Gamepad.sThumbRY>=XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ||
			m_state.Gamepad.sThumbRY<=-XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
				WORLDMODEL->playerLookUpDown(-10*((float)m_state.Gamepad.sThumbRY/(float)valueMaxStick));
	}
	else
		return false;

	return true;
}